import { useMemo } from "react";
import { Menu, type MenuProps } from "antd";
import { useMatches, useNavigate } from "react-router";
import { routes } from "@/router";

type MenuItem = Required<MenuProps>["items"][number];
type Routes = typeof routes;

const menu = (function generateMenu(routes) {
  const map = new Map<string, { children?: MenuItem[]; [key: string]: any }>();
  map.set("/", { children: [] });

  function getNextPath(curr: string, next?: string) {
    if (next?.startsWith("/")) {
      return next;
    }
    let delimiter = curr.endsWith("/") ? "" : "/";
    return next ? curr + delimiter + next : curr;
  }

  function dfs(routes: Routes, curr = "/") {
    for (const route of routes) {
      const next = getNextPath(curr, route.path);
      if (route.handle?.title) {
        const item: MenuItem = {
          label: route.handle.title,
          key: next,
        };
        if (!map.has(next)) {
          map.set(next, item);
        }
        const parent = map.get(curr)!;
        parent.children = parent?.children || [];
        parent.children.push(item);
      }
      if (route.children) {
        dfs(route.children, next);
      }
    }
  }

  dfs(routes);

  return map.get("/")?.children;
})(routes);

export default function Aside() {
  const matches = useMatches();
  const navigate = useNavigate();

  const onClick: MenuProps["onClick"] = (e) => {
    navigate({ pathname: e.key });
  };

  const openKeys = useMemo(() => {
    const res = [];
    for (let i = 0; i < matches.length; i++) {
      if ((matches[i].handle as any)?.title) {
        res.push(matches[i].pathname);
      }
    }
    return res;
  }, [matches]);

  const selectedKeys = useMemo(() => {
    for (let i = matches.length - 1; i >= 0; i--) {
      if ((matches[i].handle as any)?.title) {
        return [matches[i].pathname];
      }
    }
    return [];
  }, [matches]);

  return (
    <aside>
      <Menu
        mode="inline"
        onClick={onClick}
        style={{ width: 256 }}
        defaultOpenKeys={openKeys}
        defaultSelectedKeys={selectedKeys}
        openKeys={openKeys}
        selectedKeys={selectedKeys}
        items={menu}
      />
    </aside>
  );
}
